package cn.edu.lzu.userweb.config;

import cn.edu.lzu.userweb.filter.UserFormAuthenticationFilter;
import cn.edu.lzu.userweb.realm.UserRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @PackageName: cn.edu.lzu.unitweb.config
 * @ClassName: ShiroConfig
 * @Description: TODO shiro的配置
 * @Author: 张琦[QQ:3098086691]
 * @Date: 2019/11/28 10:43
 * @Version: 1.0
 */

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(getSecurityManager());
        //设置自定义的UserFormAuthenticationFilter
        Map<String, Filter> filterMap=shiroFilterFactoryBean.getFilters();
        filterMap.put("authc", new UserFormAuthenticationFilter());

        //设置过滤器链
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/node_modules/**", "anon");
        filterChainDefinitionMap.put("/images/**", "anon");
        filterChainDefinitionMap.put("/lib/**", "anon");
        filterChainDefinitionMap.put("/userLogin", "anon");////////////////////////////////////
        filterChainDefinitionMap.put("/index", "anon");
        filterChainDefinitionMap.put("/yiyuan", "anon");
        filterChainDefinitionMap.put("/taocan", "anon");
        filterChainDefinitionMap.put("/baozhuzhongxin", "anon");
        filterChainDefinitionMap.put("/guanyuwomen", "anon");
        filterChainDefinitionMap.put("/getAllProvince", "anon");
        filterChainDefinitionMap.put("/getAllCityByProvinceId", "anon");
        filterChainDefinitionMap.put("/getAllCountyByCityId", "anon");
        filterChainDefinitionMap.put("/getUnitsByProvinceId", "anon");
        filterChainDefinitionMap.put("/getUnitsByCityId", "anon");
        filterChainDefinitionMap.put("/getUnitsByAreaId", "anon");
        filterChainDefinitionMap.put("/xiangqing", "anon");
        filterChainDefinitionMap.put("/getUnitPackages", "anon");
        filterChainDefinitionMap.put("/mingxi", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/userLogin", "anon");
        filterChainDefinitionMap.put("/yuyue", "authc");
        filterChainDefinitionMap.put("/bookExamine", "authc");
        filterChainDefinitionMap.put("/logout", "authc");
        filterChainDefinitionMap.put("/user", "authc");
        filterChainDefinitionMap.put("/userdingdan", "authc");
        filterChainDefinitionMap.put("/userdingdanwcg", "authc");
        filterChainDefinitionMap.put("/userdingdanwc", "authc");
        filterChainDefinitionMap.put("/baogao", "authc");
        filterChainDefinitionMap.put("/anquan", "authc");
        filterChainDefinitionMap.put("/", "authc");
        filterChainDefinitionMap.put("/**", "authc");

        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * @Author: 张琦[QQ:3098086691]
     * @Description: TODO 安全管理器
     * @Date: 2019/11/28 11:21
     * @Param: []
     * @Return: org.apache.shiro.web.mgt.DefaultWebSecurityManager
     **/
    @Bean
    public DefaultWebSecurityManager getSecurityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //设置‘用户认证器’，它通过调用realm判断当前登录的用户身份
        defaultWebSecurityManager.setAuthenticator(getModularRealmAtuhenticator());
        //设置realm
        Collection<Realm> realms = new ArrayList<>();
        //要使用注入到spring中的bean
        realms.add(getUserRealm());
        defaultWebSecurityManager.setRealms(realms);
        //设置‘会话管理器’
        defaultWebSecurityManager.setSessionManager(getSessionManager());
        return defaultWebSecurityManager;
    }

    /**
     * @Author: 张琦[QQ:3098086691]
     * @Description: TODO 用户认证器，设置认证策略设置为至少有一个realm认证成功
     * @Date: 2019/11/28 12:24
     * @Param: []
     * @Return: org.apache.shiro.authc.pam.ModularRealmAuthenticator
     **/
    @Bean
    public ModularRealmAuthenticator getModularRealmAtuhenticator() {
        ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
        modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return modularRealmAuthenticator;
    }

    /**
     * @Author: 张琦[QQ:3098086691]
     * @Description: TODO 设置会话管理器
     * @Date: 2019/11/28 12:34
     * @Param: []
     * @Return: org.apache.shiro.session.mgt.SessionManager
     **/
    @Bean
    public SessionManager getSessionManager() {
//        SessionManager是抽象类，它的三个实现类分别是：
//        1)：DefaultSessionManager, 使用默认的实现，用于javaSE环境
//        2)：ServletContainerSessionManager, 用于web环境，其直接使用servlet容器的会话
//        3)：DefaultWebSessionManager, 用于Web环境的实现，可以替代ServletContainerSessionManager，自己维护着会话，直接废弃了Servlet容器的会话管理。
//        DefaultWebSessionManager defaultWebSessionManager =  new DefaultWebSessionManager();
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        //设置session失效时间，默认30分钟；这里暂时设置为测试时间
        defaultWebSessionManager.setGlobalSessionTimeout(1000*30);
        //删除失效的session
        defaultWebSessionManager.setDeleteInvalidSessions(true);
        //注入自定义的监听器
        Collection<SessionListener> listeners=new ArrayList<>();
        //listeners.add(examinerListener);
        defaultWebSessionManager.setSessionListeners(listeners);
        //设置自己的sessionDao
        //defaultWebSessionManager.setSessionDAO(examinerSessionDao);

        return defaultWebSessionManager;
    }

    /**
     * @Author: 张琦[QQ:3098086691]
     * @Description: TODO 自定义realm：ExaminerRealm
     * @Date: 2019/11/28 13:33
     * @Param: []
     * @Return: cn.edu.lzu.unitweb.realm.ExaminerRealm
     **/
    @Bean
    public UserRealm getUserRealm() {
        UserRealm userRealm = new UserRealm();
        //设置凭证匹配器，设定加密算法和迭代次数
        //userRealm.setCredentialsMatcher(getHashedCredentialsMatcher());
        return userRealm;
    }

    /**
     * @Author: 张琦[QQ:3098086691]
     * @Description: TODO 凭证匹配器
     * @Date: 2019/11/28 13:41
     * @Param: []
     * @Return: org.apache.shiro.authc.credential.HashedCredentialsMatcher
     **/
    @Bean
    public HashedCredentialsMatcher getHashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
        //加密算法
        hashedCredentialsMatcher.setHashAlgorithmName("Md5");
        //迭代次数
        hashedCredentialsMatcher.setHashIterations(5);
        //false:默认的Base64编码；true：Hex编码
        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(false);
        return hashedCredentialsMatcher;
    }


}
